package com.shyroke.daydayzhuanweb.controller;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.querydsl.jpa.impl.JPAQuery;
import com.querydsl.jpa.impl.JPAQueryFactory;
import com.shyroke.daydayzhuanapi.constant.Constant;
import com.shyroke.daydayzhuanapi.constant.LoginErrorCodeConstant;
import com.shyroke.daydayzhuanapi.constant.RedisKeyPrefix;
import com.shyroke.daydayzhuanapi.constant.UserStatusConstant;
import com.shyroke.daydayzhuanapi.dto.*;
import com.shyroke.daydayzhuanapi.entity.*;
import com.shyroke.daydayzhuanapi.mapper.ProjectMapper;
import com.shyroke.daydayzhuanapi.mapper.SysNoticeMapper;
import com.shyroke.daydayzhuandao.respository.MenuRepository;
import com.shyroke.daydayzhuandao.respository.NewsRepository;
import com.shyroke.daydayzhuandao.respository.ProjectRepository;
import com.shyroke.daydayzhuandao.respository.UserRepository;
import com.shyroke.daydayzhuansvc.service.ISysDownService;
import com.shyroke.daydayzhuansvc.util.*;
import org.apache.commons.lang.BooleanUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.subject.Subject;
import org.jsoup.Connection;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.select.Elements;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpSession;
import java.net.URLDecoder;
import java.util.*;
import java.util.stream.Collectors;


/**
 * 类名 ：后台用户controller
 * 用法 ：
 * 创建人 ： shyroke
 * 时间：2018/12/11 10:46
 */
@Controller
@RequestMapping(value = "admin")
public class AdminController extends  BaseController{

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private UserRepository userRepository;
    @Autowired
    private ProjectRepository projectRepository;
    @Autowired
    private JPAQueryFactory factory;
    @Autowired
    private ISysDownService sysDownService;
    @Autowired
    private NewsRepository newsRepository;
    @Autowired
    private SysNoticeMapper sysNoticeMapper;
    @Autowired
    private MenuRepository menuRepository;
    @Autowired
    private ProjectMapper projectMapper;
    @Autowired
    private RedisTemplate redisTemplate;


    /**
     * 登录
     * @return
     */
    @RequestMapping(value = "/tologin")
    @ResponseBody
    public R login(UserLoginRequest user, HttpSession session, @RequestParam("code") String code){

//        校验验证码
        String sysCode = session.getAttribute(RandomValidateCodeUtil.RANDOMCODEKEY).toString();

        if(!sysCode.equals(code)){
            return R.error(LoginErrorCodeConstant.VERICODE_ERR);
        }

        AuthenticationToken usernamePasswordToken = new UsernamePasswordToken(user.getName(),user.getPassword());

        Subject subject = SecurityUtils.getSubject();


        try {
            UserEntity curren_user = userRepository.findByName(user.getName());
            if(curren_user == null){
                logger.info("用户不存在！");
                return R.error("用户不存在!");
            }

            if(curren_user.getStatus().intValue() == UserStatusConstant.FORZEN){
                return R.error("账号被冻结！请联系站长处理！");
            }


            subject.login(usernamePasswordToken);
            UserMain user1 = new UserMain();
            BeanUtils.copyProperties(curren_user,user1);
            subject.getSession().setAttribute("user",user1);
            curren_user.setLastLoginTime(new Date());
            userRepository.save(curren_user);

        }catch (UnknownAccountException ex) {
            logger.info("用户名错误！");
            return R.error("用户名错误!");
        } catch (IncorrectCredentialsException ex) {
            logger.info("密码错误！");
            return R.error("密码错误!");
        } catch (AuthenticationException ex) {
            logger.info(ExceptionUtil.getMessage(ex));
            return R.error("系统错误，请查看日志");
        } catch (Exception ex) {
            logger.info(ExceptionUtil.getMessage(ex));
            return R.error("系统错误，请查看日志");
        }

        return R.ok("登录成功！");
    }


    @PermissionAnnotation(permissionName = "boke:*")
    @PostMapping(value = "desc")
    @ResponseBody
    public R desc(){
        return R.ok("删除成功！");
    }

    /**
     * 管理员登录首页
     * @return
     */
    @RequestMapping(value = "index")
    public ModelAndView index(ModelAndView model,HttpSession session){

        UserMain user = (UserMain)session.getAttribute("user");
        Set<RoleEntity> roleList = userRepository.findByName(user.getName()).getRoleList();
        boolean isAdmin = UserUtils.isAdmin2(roleList);
        //获取未读消息数量
        List<NewsEntity> newsEntity = newsRepository.findByIsRead(0);
        int noReadCount = newsEntity==null?0:newsEntity.size();

        String img;
        if(isAdmin){
            img = "/img/logo.png";
        }else {
            img = "/img/user.png";
        }

        model.addObject("noReadCount",noReadCount);
        model.addObject("user",user);
        model.addObject("img",img);
        model.setViewName("admin/index");

        return model;
    }

    /**
     * 首页信息
     * @return
     */
    @RequestMapping(value = "main")
    public ModelAndView main(ModelAndView model,HttpSession session){
        UserMain user = (UserMain)session.getAttribute("user");
        model.addObject("user",user);
        model.addObject("/admin/main");
        model.addObject("info",getInfo(user));
        Set<RoleEntity> roleList = userRepository.findByName(user.getName()).getRoleList();
        Boolean isAdmin = UserUtils.isAdmin2(roleList);
        model.addObject("isAdmin",isAdmin);
        return model;
    }

    /**
     * 获取菜单
     * @return
     */
    @RequestMapping(value = "getMenus")
    @ResponseBody
    public List<MenuTree> getMenus(HttpSession session){
        UserMain user = (UserMain)session.getAttribute("user");
        Set<RoleEntity> roleList = userRepository.findByName(user.getName()).getRoleList();
        List<MenuEntity>  menuList = new ArrayList<>();
        if(!CollectionUtils.isEmpty(roleList)){
            for(RoleEntity role:roleList){
                List<MenuEntity> list = menuRepository.findByRoleId(role.getId());
                menuList.addAll(list);
            }
        }

        List<MenuTree> childernMenus = new ArrayList<>();
        List<MenuTree> parentMenus = new ArrayList<>();
        List<MenuTree> result = new ArrayList<>();
        //1、先取出父子节点
        MenuTree menuTree = null;
        for(MenuEntity menu:menuList){
            menuTree = new MenuTree(menu.getMid(),menu.getParentid(),menu.getName(), menu.getHref(), menu.getIcon(), BooleanUtils.toBoolean(menu.getSpread()));
            if(menu.getParentid() == 0){
                parentMenus.add(menuTree);
            }else{
                childernMenus.add(menuTree);
            }
        }

        for(MenuTree parent:parentMenus){
            List<MenuTree> childMenus = parent.getChildren();
            for(MenuTree menu:childernMenus){
                if(menu.getParentid() == parent.getMid()){
                    childMenus.add(menu);
                    parent.setChildren(childMenus);
                }
            }
            result.add(parent);
        }

        return result;
    }

    private int getTodayCount() {
        String todayKey = RedisKeyPrefix.PROJECTVIEW+":today";
        Object todayCountObj = redisTemplate.opsForValue().get(todayKey);
        int todayCount = 0;
        if(todayCountObj != null) {
            List<String> list = (List<String>) todayCountObj;
            Set<String> sets = list.stream().collect(Collectors.toSet());
            todayCount = sets.size();
        }
        return todayCount;
    }



    /**
     * 获取最新5条文章
     * @return
     */
    @RequestMapping(value = "getNewArticleList")
    @ResponseBody
    public List<ProjectDto> getNewArticleList(HttpSession session){
        List<ProjectEntity> result = new ArrayList<>(5);
        UserMain user = (UserMain)session.getAttribute("user");
        Set<RoleEntity> roleList = userRepository.findByName(user.getName()).getRoleList();
        Boolean isAdmin = UserUtils.isAdmin2(roleList);

        QProjectEntity qProjectEntity = QProjectEntity.projectEntity;
        JPAQuery<ProjectEntity> query = factory.selectFrom(qProjectEntity);

        if(!isAdmin && user.getId() != null){
            query = query.where(qProjectEntity.createId.eq(user.getId()));
        }
        result = query.orderBy(qProjectEntity.createTime.desc()).limit(5).fetch();
        return result.stream().map(e -> projectMapper.entityToDto(e)).collect(Collectors.toList());
    }


    /**
     * 获取首页信息，包括文章数、上次登陆时间
     * @return
     */
    public Map<String,Object> getInfo(UserMain user){
        Map<String,Object> result = new HashMap<>();
        Set<RoleEntity> roleList = userRepository.findByName(user.getName()).getRoleList();
        Boolean isAdmin = UserUtils.isAdmin2(roleList);

        String endDate = DateUtils.getToday() + " 23:59:59";
        String beginDate = DateUtils.getBefore(7) + " 00:00:00";

        //统计文章总数
        int projectCount = 0;
        //一周新增文章数
        List<ProjectEntity> projectList = new ArrayList<>();
        //一周新增阅读量
        int weekReadCount = 0;
        //总评论量
        int commentCount = 0;
        //一周评论量
        int weekCommentCount = 0;

        //未读消息
        List<NewsEntity> newsEntityList = newsRepository.findByIsReadAndUserId(0, user.getId());
        result.put("unReadNews",newsEntityList==null?0:newsEntityList.size());

        //下载量
        SysDownDto sysDown = sysDownService.getSysDown();
        int todayDownCount = sysDown.getTodayCount();
        int allDownCount = sysDown.getCount();
        int todayCount = this.getTodayCount();
        result.put("todayDownCount",todayDownCount);
        result.put("allDownCount",allDownCount);
        result.put("todayCount",todayCount);

        if(isAdmin){
            //统计文章总数
            projectCount = (int)projectRepository.count();

            //一周新增文章数
            projectList = projectRepository.findByWeek(beginDate,endDate);

            //一周新增阅读量
            weekReadCount = countReac(projectList);

            //文章获得评论量
            Integer comementAllCount = projectRepository.commentCount();
            commentCount = comementAllCount == null?0:comementAllCount;

            //一周文章获得评论量
            weekCommentCount = countComment(projectList);
        }else{
            //统计文章总数
            projectCount = projectRepository.countByUid(user.getId());
            //一周新增文章数
            projectList = projectRepository.findByWeekAndUid(beginDate,endDate,user.getId());

            result.put("weekProjectCount",CollectionUtils.isEmpty(projectList)?0:projectList.size());

            //一周新增阅读量
            weekReadCount = countReac(projectList);

            //总评论量
            Integer commentAllCount = projectRepository.commentCountByUid(user.getId());
            commentCount = commentAllCount == null?0:commentAllCount;
            //一周评论量
            weekCommentCount = countComment(projectList);
        }

        //统计文章总数
        result.put("projectCount",projectCount);
        result.put("weekProjectCount",CollectionUtils.isEmpty(projectList)?0:projectList.size());
        result.put("weekReadCount",weekReadCount);
        result.put("commentCount",commentCount);
        result.put("weekCommentCount",weekCommentCount);

        return result;
    }

    /**
     * 统计评论量
     * @param projectList
     * @return
     */
    private int countComment(List<ProjectEntity> projectList) {
        if(CollectionUtils.isEmpty(projectList)){
            return 0;
        }
        int sum = 0;
        for(ProjectEntity project:projectList){
            sum += project.getCommentMount();
        }
        return sum;
    }

    /**
     * 统计阅读量
     * @param projectList
     * @return
     */
    private int countReac(List<ProjectEntity> projectList) {
        if(CollectionUtils.isEmpty(projectList)){
            return 0;
        }
        int sum = 0;
        for(ProjectEntity project:projectList){
            sum += project.getReadMount();
        }
        return sum;
    }


    /**
     * 获取最新公告内容
     * @return
     */
    @RequestMapping(value = "getNotice")
    @ResponseBody
    public SysNoticeDto getNotice(){
        QSysNoticeEntity qSysNoticeEntity = QSysNoticeEntity.sysNoticeEntity;
        List<SysNoticeEntity> list = factory.selectFrom(qSysNoticeEntity).orderBy(qSysNoticeEntity.id.desc()).limit(1).fetch();
        if(CollectionUtil.isNotEmpty(list)){
            return sysNoticeMapper.entityToDto(list.get(0));
        }
        return null;
    }


    /**
     * 登录
     * @return
     */
//    @RequestMapping(value = "/register")
//    @ResponseBody
//    public R register(User user){
//        try {
//            //校验邮箱是否已经存在
//            User userByName = userMapper.getUserByName(user.getEmail());
//            if(userByName != null){
//                return R.error("邮箱已经存在！");
//            }
//
//            user.setName(user.getEmail());
//            user.setStatus(UserStatusConstant.NORMAL);
//            user.setTouxiang("img/cover/default.png");
//            userMapper.insertSelective(user);
//            //保存角色
//            UserRole userRole = new UserRole();
//            userRole.setUserid(user.getUid());
//            userRole.setRoleid(2);
//            userRoleMapper.insertSelective(userRole);
//
//        }catch (Exception ex) {
//            logger.info(ExceptionUtil.getMessage(ex));
//            return R.error("系统错误，请查看日志");
//        }
//        return R.ok("注册成功！");
//    }


    /**
     * 获取关键词提示
     * @return
     */
    @RequestMapping(value = "getKeywords")
    @ResponseBody
    public R getKeywords(String key){
        Map<String,List<String>> res = new HashMap<>();
        if(StrUtil.isBlank(key)){
            return R.error("关键词不能为空！");
        }
        for (String searchName : Constant.SEARCH_MAPS.keySet()) {
            String url = Constant.SEARCH_MAPS.get(searchName);
            url = StrUtil.format(url,key);
            String body = null;
            try {
                body = HttpRequest.get(url).execute().body();
            }catch (Exception e){
                logger.info("请求搜索引擎关键词异常，",e);
                return R.error("请求搜索引擎关键词异常，请稍后重试");
            }
            if("baidu".equals(searchName)){
                try {
                    body = body.substring(body.indexOf("(")+1,body.indexOf(")"));
                    List<String> keywordList = (List<String>)JSONUtil.parse(body).getByPath("s");
                    res.put("baidu",keywordList);
                }catch (Exception e){
                    logger.info("解析百度返回关键词异常，请检查后台！",e);
                }

            }else if("sogou".equals(searchName)){
                try {
                    body = body.substring(body.indexOf("(")+1,body.indexOf(")"));
                    body = body.substring(0,body.lastIndexOf(","));
                    JSONArray jsonArray = (JSONArray) JSONUtil.parse(body);
                    List<String> keywordList = (List<String>)jsonArray.get(1);
                    res.put("sogou",keywordList);
                }catch (Exception e){
                    logger.info("解析搜狗返回关键词异常，请检查后台！",e);
                }

            }else if("bing".equals(searchName)){
                try {
                    body = body.substring(body.indexOf("callback("),body.lastIndexOf(")"));
                    body = body.substring(0,body.indexOf("/*"));
                    body = body.replace("callback(","");
                    JSONObject jsonObject = (JSONObject)JSONUtil.parse(body).getByPath("AS");
                    JSONArray jsonArray = (JSONArray)jsonObject.get("Results");
                    JSONObject obj = (JSONObject)jsonArray.get(0);
                    JSONArray dataArr = (JSONArray)obj.get("Suggests");
                    List<String> keywordList = dataArr.stream().map(d -> {
                        JSONObject data = (JSONObject) d;
                        return data.get("Txt").toString();
                    }).collect(Collectors.toList());
                    res.put("bing",keywordList);
                }catch (Exception e){
                    logger.info("解析bing返回关键词异常，请检查后台！",e);
                }
            }else if("baiduRelation".equals(searchName)){
                try {
                    String baiduUrl = Constant.SEARCH_MAPS.get(searchName);
                    baiduUrl = StrUtil.format(baiduUrl, URLDecoder.decode(key));
                    Connection conn = Jsoup.connect(baiduUrl).timeout(5000);
                    conn.header("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8");
                    conn.header("Accept-Encoding", "gzip, deflate, sdch");
                    conn.header("Accept-Language", "zh-CN,zh;q=0.8");
                    conn.header("User-Agent", "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36");
                    Document document = conn.get();

                    Elements tds = document.select("div#rs_new table td");
                    List<String> keywordList = tds.stream().map(t -> t.text()).collect(Collectors.toList());
                    res.put("baiduRelation",keywordList);
                }catch (Exception e){
                    logger.info("解析baiduRelation返回关键词异常，请检查后台！",e);
                }
            }
        }
        return R.ok("data",res);
    }
}
